﻿using Newtonsoft.Json;
using SqlSugar;
using SupDataSync.Common;
using SupDataSync.Model;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Web.Configuration;
using DataSyncCommon;

namespace SupDataSync.ChildForms
{
    /// <summary>
    /// 业务数据同步
    /// </summary>
    public partial class FrmBusiDataSync : Form
    {
        private string CustomerCode { get; set; }
        private DataTable DataSource { get; set; }

        public FrmBusiDataSync()
        {
            InitializeComponent();
        }

        private void FrmBusiDataSync_Load(object sender, EventArgs e)
        {
            this.dtp_StartDate.Value = DateTime.Now.AddDays(1 - DateTime.Now.DayOfYear);
            this.dgView_BaseTable.AutoGenerateColumns = false;
        }

        /// <summary>
        /// 窗体显示事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmBaseDataSync_Shown(object sender, EventArgs e)
        {
            try
            {
                string sql = "select t.customercode,t.custormername from ba_customer t where t.isused=1 " +
                    "and t.customercode not in (20520001,20510002) order by t.customercode desc";//贵州四川 and t.customercode not in (20520001,20510002)";
                DataSet ds_customer = null;
                DbHelperMySql.ExecuteQuery(sql, out ds_customer);
                if (ds_customer != null && ds_customer.Tables.Count > 0 && ds_customer.Tables[0].Rows.Count > 0)
                {
                    this.cmb_Customer.DataSource = ds_customer.Tables[0];
                    this.cmb_Customer.DisplayMember = "custormername";
                    this.cmb_Customer.ValueMember = "customercode";
                }
            }
            catch (Exception err)
            {
                MessageBox.Show(err.Message,"提示");
            }
        }

        /// <summary>
        /// 查询事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_Query_Click(object sender, EventArgs e)
        {
            Query();
        }

        /// <summary>
        /// 查询方法
        /// </summary>
        private void Query()
        {
            DataSource = null;
            this.dgView_BaseTable.DataSource = null;
            CustomerCode = "";

            var customerCd = this.cmb_Customer.SelectedValue + "";
            var customerName = this.cmb_Customer.Text + "";
            var startDate = this.dtp_StartDate.Value.ToString("yyyy-MM-dd");
            string sql = @"select 1 as seq,'发货单' as businame,'order_no' as tablename,count(*) as rowcount,r.CUSTOMERCODE
from order_no r left join ba_customer c on r.CUSTOMERCODE=c.customercode
 where r.CUSTOMERCODE='{0}' and DATE(r.ORDER_DATE) > '{1}'
union all
select 2 as seq,'发货单明细' as businame,'order_manage' as tablename,count(*) as rowcount,m.CUSTOMERCODE
 from order_manage m where m.CUSTOMERCODE='{0}' and DATE(m.DELIVERY_DATE)> '{1}'
union all
select 3 as seq,'发货单明细条码' as businame,'order_manage_list' as tablename,count(*) as rowcount,m.CUSTOMERCODE
 from order_manage_list l left join order_manage m on l.order_id=m.order_id
where m.CUSTOMERCODE='{0}' and DATE(m.DELIVERY_DATE)> '{1}'
union all
select 4 as seq,'大件条码' as businame,'pp_big_lab_sup' as tablename,count(*) as rowcount,b.CUSTOMERCODE
from pp_big_lab_sup b where b.CUSTOMERCODE='{0}' and DATE(b.CREATE_DT)>'{1}'
union all
select 5 as seq,'小件条码' as businame,'pp_lab_lst_sup' as tablename,count(*) as rowcount,s.CUSTOMERCODE
from pp_lab_lst_sup s where s.CUSTOMERCODE='{0}' and DATE(s.CREATE_DT)>'{1}'";

            sql = string.Format(sql, customerCd, startDate);
            DataSet ds;
            DbHelperMySql.ExecuteQuery(sql, out ds);
            if (ds != null && ds.Tables.Count > 0)
            {
                CustomerCode = customerCd;

                var dt = ds.Tables[0];
                dt.Columns.Add("custormername", Type.GetType("System.String"));
                dt.Columns.Add("syncmsg", Type.GetType("System.String"));
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    dt.Rows[i]["syncmsg"] = "";
                    dt.Rows[i]["custormername"] = customerName;
                }

                DataSource = dt;
                this.dgView_BaseTable.DataSource = dt;
            }

        }

        /// <summary>
        /// 同步全部
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_SyncAll_Click(object sender, EventArgs e)
        {
            ClearSyncInfo();
            if (this.dgView_BaseTable.DataSource == null || this.dgView_BaseTable.Rows.Count == 0)
            {
                MessageBox.Show("无数据，请先查询需要同步的表数据！","提示");
                return;
            }
            SyncBaseDataAll(CustomerCode);
        }

        /// <summary>
        /// 同步所有表
        /// </summary>
        /// <param name="customercd"></param>
        private void SyncBaseDataAll(string customercd)
        {
            try
            {
                var model = new SyncBusinessModel();
                model.CustomerCode = customercd;
                model.TenantId = SysConfig.TenantId;
                var startDate = this.dtp_StartDate.Value;

                //获取本地基础表数据
                using (var db = DbHelperMySql.GetSqlSugarDb())
                {

                    model.OrderList = db.Queryable<order_no>()
                        .Where(p => p.CUSTOMERCODE == customercd && p.ORDER_DATE >= startDate)
                        .OrderBy(p => p.ORDER_DATE)
                        .ToList();

                    model.OrderManageList = db.Queryable<order_manage>()
                        .Where(b => b.CUSTOMERCODE == customercd && b.DELIVERY_DATE >= startDate)
                        .OrderBy(p => p.DELIVERY_DATE)
                        .ToList();

                    model.OrderManageDetailList = db.Queryable<order_manage_list, order_manage>((l, m) => new object[]{
                            JoinType.Left, l.ORDER_ID == m.ORDER_ID })
                        .Where((l, m) => m.CUSTOMERCODE == customercd && l.SCAN_TIME >= startDate)
                        .OrderBy((l, m) => l.SCAN_TIME)
                        .Select((l, m) => l)
                        .ToList();

                    model.BigBarcodeList = db.Queryable<pp_big_lab_sup>()
                        .Where(p => p.CUSTOMERCODE == customercd && p.CREATE_DT >= startDate)
                        .OrderBy(p => p.CREATE_DT)
                        .ToList();

                    //大量数据
                    model.SmallBarcodeList = db.Queryable<pp_lab_lst_sup>()
                     .Where(p => p.CUSTOMERCODE == customercd && p.CREATE_DT >= startDate)
                     .OrderBy(p => p.CREATE_DT)
                     .ToList(); model.SmallBarcodeList = db.Queryable<pp_lab_lst_sup>()
                      .Where(p => p.CUSTOMERCODE == customercd && p.CREATE_DT >= startDate)
                      .OrderBy(p => p.CREATE_DT)
                      .ToList();

                }

                var url = SysConfig.SyncBusinessApiUrl;
                var reqjson = JsonConvert.SerializeObject(model);
                var responseStr = HttpHelper.WebRequestApi(url, reqjson, "POST");
                var syncResultList = JsonConvert.DeserializeObject<List<SyncResultModel>>(responseStr);


                //刷新同步结果
                RefreshSyncResult(syncResultList, "");

                ShowMsg("同步结束！");

            }
            catch (Exception err)
            {
                ShowMsg(err.Message);
                ShowMsg("同步结束！");
                MessageBox.Show(err.Message,"提示");
            }
        }

        /// <summary>
        /// 刷新同步结果信息
        /// </summary>
        /// <param name="resultList"></param>
        /// <param name="syncTableName"></param>
        private void RefreshSyncResult(List<SyncResultModel> resultList, string syncTableName)
        {
            if (resultList == null || resultList.Count == 0)
            {
                MessageBox.Show("同步失败！","提示");
                return;
            }

            for (var i = 0; i < this.DataSource.Rows.Count; i++)
            {
                var tablename = DataSource.Rows[i]["tablename"].ToString();
                var result = resultList.Where(p => p.TableName == tablename).FirstOrDefault();
                if (result != null)
                {
                    var msg = result.SyncSuccess.Value ? "同步成功！" + string.Format("插入[{0}]", result.InsertCount) : "同步失败！";
                    DataSource.Rows[i]["syncmsg"] = msg;
                }
                else
                {
                    if (!string.IsNullOrEmpty(syncTableName) && syncTableName != tablename)
                        continue;

                    DataSource.Rows[i]["syncmsg"] = "同步失败！";
                }
            }
            this.dgView_BaseTable.DataSource = null;
            this.dgView_BaseTable.DataSource = DataSource;

            var exceptionResult = resultList.Where(p => p.TableName == "Exception").FirstOrDefault();
            if (exceptionResult != null)
            {
                ShowMsg("同步过程发生异常！" + exceptionResult.SyncMsg);
            }

        }

        /// <summary>
        /// 清除同步结果信息
        /// </summary>
        private void ClearSyncInfo()
        {
            this.lb_SyncMsg.Items.Clear();
            ShowMsg("同步开始……");

            for (var i = 0; i < this.dgView_BaseTable.Rows.Count; i++)
            {
                dgView_BaseTable.Rows[i].Cells["syncmsg"].Style.BackColor = Color.White;
            }

            for (var i = 0; i < this.DataSource.Rows.Count; i++)
            {
                DataSource.Rows[i]["syncmsg"] = "";
            }

            dgView_BaseTable.DataSource = null;
            dgView_BaseTable.DataSource = DataSource;

            this.Refresh();
        }

        /// <summary>
        /// 输出信息
        /// </summary>
        /// <param name="msg"></param>
        private void ShowMsg(string msg)
        {
            var curTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss   ");
            this.lb_SyncMsg.Items.Add(curTime + msg);
            this.Refresh();
        }

        /// <summary>
        /// 同步事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dgView_BusiTable_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex >= 0)
            {
                if (e.ColumnIndex != 5)
                    return;

                try
                {
                    ClearSyncInfo();

                    DataGridViewColumn column = dgView_BaseTable.Columns[e.ColumnIndex];
                    if (column is DataGridViewButtonColumn)
                    {
                        var tablename = dgView_BaseTable.Rows[e.RowIndex].Cells["tablename"].Value.ToString();
                        var customercd = dgView_BaseTable.Rows[e.RowIndex].Cells["customercode"].Value.ToString();
                        //var supid = dgView_BaseTable.Rows[e.RowIndex].Cells["custormername"].Value.ToString();
                        SyncBaseData(tablename, customercd);
                    }
                }
                catch (Exception err)
                {
                    MessageBox.Show(err.Message,"提示");
                }
            }
        }

        /// <summary>
        /// 同步单个表
        /// </summary>
        /// <param name="tablename"></param>
        /// <param name="customercd"></param>
        /// <param name="supid"></param>
        private void SyncBaseData(string tablename, string customercd)
        {
            var model = new SyncBusinessModel();
            model.CustomerCode = customercd;
            model.TenantId = SysConfig.TenantId;
            var startDate = this.dtp_StartDate.Value;
            using (var db = DbHelperMySql.GetSqlSugarDb())
            {
                switch (tablename)
                {
                    case "order_no":
                        model.OrderList = db.Queryable<order_no>()
                            .Where(p => p.CUSTOMERCODE == customercd && p.ORDER_DATE >= startDate)
                            .OrderBy(p => p.ORDER_DATE)
                            .ToList();
                        break;
                    case "order_manage":
                        model.OrderManageList = db.Queryable<order_manage>()
                            .Where(b => b.CUSTOMERCODE == customercd && b.DELIVERY_DATE >= startDate)
                            .OrderBy(p => p.DELIVERY_DATE)
                            .ToList();
                        break;
                    case "order_manage_list":
                        model.OrderManageDetailList = db.Queryable<order_manage_list, order_manage>((l, m) => new object[]{
                            JoinType.Left, l.ORDER_ID == m.ORDER_ID })
                            .Where((l, m) => m.CUSTOMERCODE == customercd && l.SCAN_TIME >= startDate)
                            .OrderBy((l, m) => l.SCAN_TIME)
                            .Select((l, m) => l)
                            .ToList();
                        break;
                    case "pp_big_lab_sup":
                        model.BigBarcodeList = db.Queryable<pp_big_lab_sup>()
                            .Where(p => p.CUSTOMERCODE == customercd && p.CREATE_DT >= startDate)
                            .OrderBy(p => p.CREATE_DT)
                            .ToList();
                        break;
                    case "pp_lab_lst_sup":
                        //大量数据
                        model.SmallBarcodeList = db.Queryable<pp_lab_lst_sup>()
                            .Where(p => p.CUSTOMERCODE == customercd && p.CREATE_DT >= startDate)
                            .OrderBy(p => p.CREATE_DT)
                            .ToList();
                        if (model.SmallBarcodeList.Count > 10000) {
                            var icount = Math.Ceiling((decimal)model.SmallBarcodeList.Count / 5000);
                            var copymodel = DeepCopy.Clone(model);
                            copymodel.SmallBarcodeList = model.SmallBarcodeList.Take(5000).ToList();
                            Task<List<SyncResultModel>> task = CreateTask(copymodel);
                            task.Start();
                            var result = task.Result;
                            var synccount = SyncCount(result);
                            for (var i = 1; i < icount; i++)
                            {
                                copymodel.SmallBarcodeList = model.SmallBarcodeList.Skip(i * 5000).Take(5000).ToList();
                                task = CreateTask(copymodel);
                                task.Start(); 
                                synccount += SyncCount(task.Result);
                            }
                            result.Where(p => p.TableName == tablename).FirstOrDefault().InsertCount = synccount;
                            while (!task.IsCompleted)
                            {
                                Console.WriteLine(task.Status);
                                Thread.Sleep(TimeSpan.FromSeconds(1));
                            } 
                            RefreshSyncResult(result, "");
                            return;
                        }
                        break;
                }
            }

            var url = SysConfig.SyncBusinessApiUrl;
            var reqjson = JsonConvert.SerializeObject(model);
            var responseStr = HttpHelper.WebRequestApi(url, reqjson, "POST");
            var syncResultList = JsonConvert.DeserializeObject<List<SyncResultModel>>(responseStr);

            //刷新同步结果
            RefreshSyncResult(syncResultList, "");

            ShowMsg("同步结束！");
        }
        /// <summary>
        /// 返回执行统计结果
        /// </summary>
        /// <param name="syncResults"></param>
        /// <returns></returns>
        public int SyncCount(List<SyncResultModel> syncResults) {
            int i = 0;
            foreach (var item in syncResults) {
                i+=(int)item.InsertCount;
            }
            return i;
        }
        public Task<List<SyncResultModel>> CreateTask(SyncBusinessModel model) {
            return new Task<List<SyncResultModel>>(()=>TaskSync(model));
        } 
        /// <summary>
        /// 同步方法
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public List<SyncResultModel> TaskSync(SyncBusinessModel model) {
            var url = SysConfig.SyncBusinessApiUrl;
            var reqjson = JsonConvert.SerializeObject(model);
            var responseStr = HttpHelper.WebRequestApi(url, reqjson, "POST");
            var syncResultList = JsonConvert.DeserializeObject<List<SyncResultModel>>(responseStr);
            return syncResultList;
        }

        private void 帮助ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("1.选择客户及数据起始时间，点击[查询]；" +
                "\n2.点击[同步全部]将同步所有数据；" +
                "\n3.选择单项，点击[同步]只会同步当前选择的表；" +
                "\n4.下方可查看同步信息结果。", "怎么配置连接");
        }
    }
}
